package org.lex.ftp.ui.explorer.file;

import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Collections;

import javax.swing.JTable;
import javax.swing.SortOrder;
import javax.swing.RowSorter.SortKey;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableRowSorter;

import org.lex.catalog.CatalogEvent;
import org.lex.ftp.model.FTPModel;
import org.lex.ftp.model.NullFTPModel;
import org.lex.net.ftp.IFTPFile;
import org.lex.swing.table.DateRenderer;
import org.lex.utils.CategoryComparator;
import org.lex.utils.Comparators;


public class FTPFileExplorer extends JTable {
	private FTPFileTableModel tableModel;
	private FTPModel ftpModel = NullFTPModel.getInstance();

	public FTPFileExplorer() {
		super();
		initialize();
	}

	public FTPModel getFTPModel() {
		return ftpModel;
	}

	public void setFTPModel(FTPModel model) {
		if (null != this.ftpModel)
			this.ftpModel.removeCatalogListener(this.getModel());
		this.ftpModel = model;
		this.ftpModel.addCatalogListener(this.tableModel);
		this.tableModel.catalogChanged(new CatalogEvent(model, model.getCatalog()));
	}

	public IFTPFile getSelectedFile() {
		int row = this.getSelectedRow();
		if (-1 == row)
			return null;
		row = this.convertRowIndexToModel(row);
		return this.getModel().getFtpFile(row);
	}

	public int getSelectedFilesCount() {
		return this.getSelectedRowCount();
	}

	public IFTPFile[] getSelectedFiles() {
		int[] rows = this.getSelectedRows();
		// if( 0 == rows.length )
		// return FtpUtilities.EMPTY;
		IFTPFile[] items = new IFTPFile[rows.length];
		for (int i = 0; i < rows.length; i++) {
			rows[i] = this.convertRowIndexToModel(rows[i]);
			items[i] = this.getModel().getFtpFile(rows[i]);
		}
		return items;
	}

	public IFTPFile[] getAllFiles() {
		IFTPFile[] files = new IFTPFile[this.getModel().getRowCount()];
		for (int i = 0; i < files.length; i++)
			files[i] = getModel().getFtpFile(convertRowIndexToModel(i));
		return files;
	}

	public IFTPFile getFtpFile(int viewRowIndex) {
		int modelRow = this.convertRowIndexToModel(viewRowIndex);
		return this.getModel().getFtpFile(modelRow);
	}

	@Override
	public FTPFileTableModel getModel() {
		if (null == tableModel)
			this.tableModel = new FTPFileTableModel();
		return tableModel;
	}

	private void initialize() {
		this.setName(this.getClass().getName() + ".table");
		// initialize table
		this.setModel(this.getModel());
		this.setShowGrid(false);
		this.setFillsViewportHeight(true);
		this.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
		// set column renderer and width
		TableColumnModel model = this.getColumnModel();
		int[] width = { 225, 100, 125 };
		TableCellRenderer[] renderers = { new FileNameRenderer(), new FTPFileSizeRenderer(), new DateRenderer() };
		for (int i = 0; i < this.getColumnCount(); i++) {
			TableColumn column = model.getColumn(i);
			column.setPreferredWidth(width[i]);
			if (null != renderers[i])
				column.setCellRenderer(renderers[i]);
		}
		// set sorter
		TableRowSorter<FTPFileTableModel> sorter = new TableRowSorter<FTPFileTableModel>(this.getModel());
		sorter.setComparator(0, Comparators.newComparator(new CategoryComparator<IFTPFile>() {
			public int compare(IFTPFile e1, IFTPFile e2) {
				return e1.getName().compareTo(e2.getName());
			}

			public int getCategory(IFTPFile element) {
				if (element.isDirectory())
					return 0;
				else
					return 1;
			}
		}));
		sorter.setComparator(1, Comparators.newComparator(new CategoryComparator<IFTPFile>() {
			public int compare(IFTPFile e1, IFTPFile e2) {
				return (int) (e1.getSize() - e2.getSize());
			}

			public int getCategory(IFTPFile element) {
				if (element.isDirectory())
					return 0;
				else
					return 1;
			}
		}));
		SortKey key = new SortKey(0, SortOrder.ASCENDING);
		sorter.setSortKeys(Collections.singletonList(key));
		this.setRowSorter(sorter);
		// add double-click handler
		this.addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				if (MouseEvent.BUTTON1 != e.getButton())
					return;
				if (e.getClickCount() < 2)
					return;
				IFTPFile file = getSelectedFile();
				if (false == file.isDirectory())
					return;
				else
					ftpModel.setCatalog(file.getName());
			}
		});
	}
}
